﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using System.Windows.Controls;

using GalaSoft.MvvmLight.Command;

using NetBay.Core.BusinessEntities;
using NetBay.Core.BusinessEntities.DashBoard;

using Rio.Applications.Web.Services;
using Rio.Framework.Localisation;
using Rio.Manager.Application.Model;
using Rio.Manager.Application.ViewModel.BaseClass;

using Telerik.Windows.Controls.Charting;

namespace Rio.Manager.Application.ViewModel.GeneralTabs
{
    public class DashboardTabViewModel : TabViewModelBase
    {
        #region Fields

        private string _busyMessage;
        private DateTime _endDate = DateTime.Now;
        private string _exportButtonContent;
        private string _exportDataButtonContent;
        private int _filesScanned;
        private ObservableCollection<ChartFolderValue> _foldersChartList;
        private int _foldersClosed;
        private int _foldersProcessed;
        private string _foldersProcessedByOperatorsByDate;
        private List<NumerizationFoldersByDate> _foldersTimeChart;
        private int _foldersToReview;
        private string _generateButtonContent;
        private string _globalInformation;
        private SeriesMappingCollection _lineSeriesMappingCollection = new SeriesMappingCollection();
        private ObservableCollection<NumerizationOperator> _operators;
        private ObservableCollection<NumerizationOperatorByDate> _operatorsByDate;
        private string _reportCloseMsg;
        private string _reportStartLabel;
        private string _reportStopLabel;
        private ObservableCollection<NumerizationOperator> _selectedOperators;
        private DateTime _startDate = DateTime.Now;
        private string _startPeriodLabel;
        private string _stopPeriodLabel;
        private string _strNbFileScan;
        private string _strNbFolderClose;
        private string _strNbFolderIncomplete;
        private string _strNbFolderProcessed;
        private string _strNbFolderRemaining;
        private string _strTotalFoldersCount;
        private string _taskProgress;
        private string _titleColumnNbFileScan;
        private string _titleColumnNbFolderProcessed;
        private string _titleColumnUserName;
        private string _titleRowTotalSum;
        private int _totalFoldersCount;
        private string _userInformation;
        private ObservableCollection<ValidationError> _validationErrors = new ObservableCollection<ValidationError>();

        #endregion Fields

        #region Constructors

        public DashboardTabViewModel()
            : base()
        {
            TabIcon = new Uri("/Rio.Manager.Application;component/Assets/Images/dashboard.png", UriKind.Relative);
        }

        #endregion Constructors

        #region Properties

        public string BusyMessage
        {
            get { return _busyMessage; }
            set
            {
                _busyMessage = value;
                RaisePropertyChanged("BusyMessage");
            }
        }

        public DateTime EndDate
        {
            get { return _endDate; }
            set
            {
                if (value == null)
                {
                    throw new Exception();
                }
                else
                {
                    _endDate = value;
                    RaisePropertyChanged("EndDate");

                    if (DateTime.Compare(StartDate, value) > 0)
                    {
                        throw new Exception(Resx.GetLabel(ResxRioManager.END_DATE_ERROR));
                    }
                }
            }
        }

        public string ExportButtonContent
        {
            get { return _exportButtonContent; }
            set
            {
                _exportButtonContent = value;
                RaisePropertyChanged("ExportButtonContent");
            }
        }

        public string ExportDataButtonContent
        {
            get { return _exportDataButtonContent; }
            set
            {
                _exportDataButtonContent = value;
                RaisePropertyChanged("ExportDataButtonContent");
            }
        }

        public int FilesScanned
        {
            get { return _filesScanned; }
            set
            {
                _filesScanned = value;
                RaisePropertyChanged("FilesScanned");
            }
        }

        public ObservableCollection<ChartFolderValue> FoldersChartList
        {
            get { return _foldersChartList; }
            set
            {
                _foldersChartList = value;
                RaisePropertyChanged("FoldersChartList");
            }
        }

        public int FoldersClosed
        {
            get { return _foldersClosed; }
            set
            {
                _foldersClosed = value;
                RaisePropertyChanged("FoldersClosed");
            }
        }

        public int FoldersProcessed
        {
            get { return _foldersProcessed; }
            set
            {
                _foldersProcessed = value;
                RaisePropertyChanged("FoldersProcessed");
            }
        }

        public string FoldersProcessedByOperatorsByDate
        {
            get { return _foldersProcessedByOperatorsByDate; }
            set
            {
                _foldersProcessedByOperatorsByDate = value;
                RaisePropertyChanged("FoldersProcessedByOperatorsByDate");
            }
        }

        public List<NumerizationFoldersByDate> FoldersTimeChart
        {
            get
            {
                return _foldersTimeChart;
            }

            set
            {
                _foldersTimeChart = value;
                RaisePropertyChanged("FoldersTimeChart");
            }
        }

        public int FoldersToReview
        {
            get { return _foldersToReview; }
            set
            {
                _foldersToReview = value;
                RaisePropertyChanged("FoldersToReview");
            }
        }

        public string GenerateButtonContent
        {
            get { return _generateButtonContent; }
            set
            {
                _generateButtonContent = value;
                RaisePropertyChanged("GenerateButtonContent");
            }
        }

        public RelayCommand GenerateReportCommand
        {
            get; private set;
        }

        public string GlobalInformation
        {
            get { return _globalInformation; }
            set
            {
                _globalInformation = value;
                RaisePropertyChanged("GlobalInformation");
            }
        }

        public RelayCommand InitializationCommand
        {
            get; set;
        }

        public SeriesMappingCollection LineSeriesMappingCollection
        {
            get { return _lineSeriesMappingCollection; }
            set
            {
                _lineSeriesMappingCollection = value;
                RaisePropertyChanged("LineSeriesMappingCollection");
            }
        }

        public ObservableCollection<NumerizationOperator> Operators
        {
            get { return _operators; }
            set
            {
                _operators = value;
                RaisePropertyChanged("Operators");
            }
        }

        public ObservableCollection<NumerizationOperatorByDate> OperatorsByDate
        {
            get { return _operatorsByDate; }
            set
            {
                _operatorsByDate = value;
                RaisePropertyChanged("OperatorsByDate");
            }
        }

        public string ReportCloseMsg
        {
            get { return _reportCloseMsg; }
            set
            {
                _reportCloseMsg = value;
                RaisePropertyChanged("ReportCloseMsg");
            }
        }

        public string ReportStartLabel
        {
            get { return _reportStartLabel; }
            set
            {
                _reportStartLabel = value;
                RaisePropertyChanged("ReportStartLabel");
            }
        }

        public string ReportStopLabel
        {
            get { return _reportStopLabel; }
            set
            {
                _reportStopLabel = value;
                RaisePropertyChanged("ReportStopLabel");
            }
        }

        public ObservableCollection<NumerizationOperator> SelectedOperators
        {
            get { return _selectedOperators; }
            set
            {
                if (value.Count > 0)
                {
                    ObservableCollection<NumerizationOperator> tempList = new ObservableCollection<NumerizationOperator>(value.Select(item => new NumerizationOperator()
                        {
                            FullName = String.Format("{0} : {1}", item.FullName, item.NbFolderProcessed),
                            NbFolderProcessed = item.NbFolderProcessed,
                            UserId = item.UserId
                        }));

                    if (Operators != null && Operators.Count > 0 && TotalFoldersCount - value.Select(item => item.NbFolderProcessed).Sum() > 0)
                    {
                        NumerizationOperator numerizationOperator = new NumerizationOperator()
                            {
                                FullName = String.Format("{0} : {1}", Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_REMAINING).TrimEnd(':'), TotalFoldersCount - value.Select(item => item.NbFolderProcessed).Sum()),
                                NbFolderProcessed = TotalFoldersCount - value.Select(item => item.NbFolderProcessed).Sum()
                            };

                        tempList.Add(numerizationOperator);
                    }

                    _selectedOperators = tempList;
                    RaisePropertyChanged("SelectedOperators");

                    FoldersTimeChart = OperatorsByDate.Where(item => item.UserId == _selectedOperators[0].UserId).FirstOrDefault().NbFoldersProcessedByDate.ToList();
                }
            }
        }

        public DateTime StartDate
        {
            get { return _startDate; }
            set
            {
                if (value == null)
                {
                    throw new Exception();
                }
                else
                {
                    _startDate = value;
                    RaisePropertyChanged("StartDate");

                    if (DateTime.Compare(value, EndDate) > 0)
                    {
                        throw new Exception(Resx.GetLabel(ResxRioManager.START_DATE_ERROR));
                    }
                }
            }
        }

        public string StartPeriodLabel
        {
            get { return _startPeriodLabel; }
            set
            {
                _startPeriodLabel = value;
                RaisePropertyChanged("StartPeriodLabel");
            }
        }

        public string StopPeriodLabel
        {
            get { return _stopPeriodLabel; }
            set
            {
                _stopPeriodLabel = value;
                RaisePropertyChanged("StopPeriodLabel");
            }
        }

        public string StrNbFileScan
        {
            get { return _strNbFileScan; }
            set
            {
                _strNbFileScan = value;
                RaisePropertyChanged("StrNbFileScan");
            }
        }

        public string StrNbFolderClose
        {
            get { return _strNbFolderProcessed; }
            set
            {
                _strNbFolderProcessed = value;
                RaisePropertyChanged("StrNbFolderClose");
            }
        }

        public string StrNbFolderIncomplete
        {
            get { return _strNbFolderIncomplete; }
            set
            {
                _strNbFolderIncomplete = value;
                RaisePropertyChanged("StrNbFolderIncomplete");
            }
        }

        public string StrNbFolderProcessed
        {
            get { return _strNbFolderClose; }
            set
            {
                _strNbFolderClose = value;
                RaisePropertyChanged("StrNbFolderProcessed");
            }
        }

        public string StrNbFolderRemaining
        {
            get { return _strNbFolderRemaining; }
            set
            {
                _strNbFolderRemaining = value;
                RaisePropertyChanged("StrNbFolderRemaining");
            }
        }

        public string StrTotalFoldersCount
        {
            get { return _strTotalFoldersCount; }
            set
            {
                _strTotalFoldersCount = value;
                RaisePropertyChanged("StrTotalFoldersCount");
            }
        }

        public string TaskProgress
        {
            get { return _taskProgress; }
            set
            {
                _taskProgress = value;
                RaisePropertyChanged("TaskProgress");
            }
        }

        public string TitleColumnNbFileScan
        {
            get { return _titleColumnNbFileScan; }
            set
            {
                _titleColumnNbFileScan = value;
                RaisePropertyChanged("TitleColumnNbFileScan");
            }
        }

        public string TitleColumnNbFolderProcessed
        {
            get { return _titleColumnNbFolderProcessed; }
            set
            {
                _titleColumnNbFolderProcessed = value;
                RaisePropertyChanged("TitleColumnNbFolderProcessed");
            }
        }

        public string TitleColumnUserName
        {
            get { return _titleColumnUserName; }
            set
            {
                _titleColumnUserName = value;
                RaisePropertyChanged("TitleColumnUserName");
            }
        }

        public string TitleRowTotalSum
        {
            get { return _titleRowTotalSum; }
            set
            {
                _titleRowTotalSum = value;
                RaisePropertyChanged("TitleRowTotalSum");
            }
        }

        public int TotalFoldersCount
        {
            get { return _totalFoldersCount; }
            set
            {
                _totalFoldersCount = value;
                RaisePropertyChanged("TotalFoldersCount");
            }
        }

        public string UserInformation
        {
            get { return _userInformation; }
            set
            {
                _userInformation = value;
                RaisePropertyChanged("UserInformation");
            }
        }

        public ObservableCollection<ValidationError> ValidationErrors
        {
            get { return _validationErrors; }
            set { _validationErrors = value; }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Inits the commands.
        /// </summary>
        public override void InitCommands()
        {
            GenerateReportCommand = new RelayCommand(GenerateReport);
            InitializationCommand = new RelayCommand(Initialization);
        }

        /// <summary>
        /// Initializations this instance.
        /// </summary>
        public void Initialization()
        {
            InitLabels();
        }

        /// <summary>
        /// Inits the labels.
        /// </summary>
        public override void InitLabels()
        {
            ReportStartLabel = Resx.GetLabel(ResxRioManager.REPORT_START_LABEL);
            ReportStopLabel = Resx.GetLabel(ResxRioManager.REPORT_STOP_LABEL);
            StartPeriodLabel = Resx.GetLabel(ResxRioManager.START_PERIODE_LABEL);
            StopPeriodLabel = Resx.GetLabel(ResxRioManager.STOP_PERIODE_LABEL);
            GenerateButtonContent = Resx.GetLabel(ResxRioManager.GENERATE_BUTTON_CONTENT);
            ExportButtonContent = Resx.GetLabel(ResxRioManager.EXPORT_BUTTON_CONTENT);
            GlobalInformation = Resx.GetLabel(ResxRioManager.GLOBAL_INFORMATION);
            StrNbFolderProcessed = Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_PROCESSED);
            StrNbFolderClose = Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_CLOSE);
            StrNbFolderIncomplete = Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_INCOMPLETE);
            StrNbFileScan = Resx.GetLabel(ResxRioManager.STR_NB_FILE_SCAN);
            StrTotalFoldersCount = Resx.GetLabel(ResxRioManager.STR_TOTAL_FOLDERS_COUNT);
            StrNbFolderRemaining = Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_REMAINING);
            TaskProgress = Resx.GetLabel(ResxRioManager.TASK_PROGRESS);
            UserInformation = Resx.GetLabel(ResxRioManager.USER_INFORMATION);
            TitleColumnUserName = Resx.GetLabel(ResxRioManager.TITLE_COLUMN_USER_NAME);
            TitleColumnNbFolderProcessed = Resx.GetLabel(ResxRioManager.TITLE_COLUMN_NB_FOLDER_PROCESSED);
            TitleColumnNbFileScan = Resx.GetLabel(ResxRioManager.TITLE_COLUMN_NB_FILE_SCAN);
            TitleRowTotalSum = Resx.GetLabel(ResxRioManager.TITLE_ROW_TOTAL_SUM);
            ExportDataButtonContent = Resx.GetLabel(ResxRioManager.EXPORT_DATA_BUTTON_CONTENT);
            ReportCloseMsg = Resx.GetLabel(ResxRioManager.REPORT_CLOSE_MSG);
            BusyMessage = Resx.GetLabel(ResxCommon.SPLASHSCREEN_MESSAGE);
            FoldersProcessedByOperatorsByDate = Resx.GetLabel(ResxRioManager.FOLDERS_PROCESSED_BY_OPERATORS_BY_DATE);
        }

        /// <summary>
        /// Clears the data.
        /// </summary>
        private void ClearData()
        {
            if (Operators != null)
            {
                Operators.Clear();
            }

            if (OperatorsByDate != null)
            {
                OperatorsByDate.Clear();
            }

            if (SelectedOperators != null)
            {
                SelectedOperators.Clear();
            }

            if (FoldersTimeChart != null)
            {
                FoldersTimeChart = null;
            }

            if (FoldersChartList != null)
            {
                FoldersChartList.Clear();
            }
        }

        /// <summary>
        /// Creates the sample data.
        /// </summary>
        private void CreateSampleData()
        {
            Random random = new Random();

            ObservableCollection<NumerizationOperator> OperatorsTemp = new ObservableCollection<NumerizationOperator>();

            for (int i = 0; i < 4; i++)
            {
                OperatorsTemp.Add(new NumerizationOperator()
                {
                    FullName = "Operator " + i.ToString(),
                    NbFileScan = random.Next(5000),
                    NbFolderClose = random.Next(5000),
                    NbFolderProcessed = random.Next(5000),
                    NbFolderToReview = random.Next(5000)
                });
            }

            Operators = OperatorsTemp;

            FilesScanned = random.Next(5000);
            TotalFoldersCount = 5000;
            FoldersProcessed = random.Next(TotalFoldersCount);
            FoldersToReview = random.Next(FoldersProcessed);

            FoldersChartList = new ObservableCollection<ChartFolderValue>();
            FoldersChartList.Add(new ChartFolderValue(Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_PROCESSED).TrimEnd(':'), FoldersProcessed));
            FoldersChartList.Add(new ChartFolderValue(Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_INCOMPLETE).TrimEnd(':'), FoldersToReview));
            FoldersChartList.Add(new ChartFolderValue(Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_REMAINING).TrimEnd(':'), TotalFoldersCount - FoldersProcessed));
        }

        /// <summary>
        /// Generates the report.
        /// </summary>
        private void GenerateReport()
        {
            if (ValidationErrors.Count == 0)
            {
                BusyIndicator.Clear();

                ClearData();

                BusinessEntitiesDomainContext l_oBEDomainContext = new BusinessEntitiesDomainContext();

                LoadGlobalInformations(l_oBEDomainContext);

                LoadOperatorsInformations(l_oBEDomainContext);
            }
        }

        /// <summary>
        /// Loads the chart operators by date informations.
        /// </summary>
        /// <param name="l_oBEDomainContext">The l_o BE domain context.</param>
        /// <param name="item">The item.</param>
        private void LoadChartOperatorsByDateInformations(BusinessEntitiesDomainContext l_oBEDomainContext, NumerizationOperator item)
        {
            BusyIndicator.AddBusyTask();

            l_oBEDomainContext.GetNumerizationFoldersReportByOperatorByDate(
                item.UserId,
                StartDate,
                EndDate,
                delegate(InvokeOperation<IEnumerable<NumerizationFoldersByDate>> retr2)
                {
                    if (retr2.Value != null)
                    {
                        BusyIndicator.RemoveBusyTask();

                        NumerizationOperatorByDate numerizationOperatorByDate = new NumerizationOperatorByDate()
                        {
                            UserId = (long)retr2.UserState,
                            FullName = item.FullName,
                        };

                        retr2.Value.ToList().ForEach(i => numerizationOperatorByDate.NbFoldersProcessedByDate.Add(i));

                        OperatorsByDate.Add(numerizationOperatorByDate);
                        RaisePropertyChanged("OperatorsByDate");
                    }
                },
                item.UserId);
        }

        /// <summary>
        /// Loads the global informations.
        /// </summary>
        /// <param name="l_oBEDomainContext">The l_o BE domain context.</param>
        private void LoadGlobalInformations(BusinessEntitiesDomainContext l_oBEDomainContext)
        {
            BusyIndicator.AddBusyTask();

            //Global Informations
            l_oBEDomainContext.GetNumerizationReport(
                StartDate,
                EndDate,
                delegate(InvokeOperation<IEnumerable<NumerizationResum>> retr)
                {
                    if (retr.Value != null && retr.Value.Count() > 0)
                    {
                        BusyIndicator.RemoveBusyTask();

                        NumerizationResum resum = ((IEnumerable<NumerizationResum>)retr.Value).First();
                        FilesScanned = resum.FilesScanned;
                        FoldersProcessed = resum.FoldersProcessed;
                        FoldersClosed = resum.FoldersClosed;
                        FoldersToReview = resum.FoldersToReview;
                        TotalFoldersCount = resum.TotalFoldersCount;

                        /*
                         * Build General Chart
                         */

                        FoldersChartList = new ObservableCollection<ChartFolderValue>();
                        FoldersChartList.Add(new ChartFolderValue(Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_PROCESSED), FoldersProcessed));

                        if (TotalFoldersCount - FoldersProcessed > 0)
                        {
                            FoldersChartList.Add(new ChartFolderValue(Resx.GetLabel(ResxRioManager.STR_NB_FOLDER_REMAINING), TotalFoldersCount - FoldersProcessed));
                        }
                    }

                },
                null);
        }

        /// <summary>
        /// Loads the operators informations.
        /// </summary>
        /// <param name="l_oBEDomainContext">The l_o BE domain context.</param>
        private void LoadOperatorsInformations(BusinessEntitiesDomainContext l_oBEDomainContext)
        {
            BusyIndicator.AddBusyTask();

            //Operators Informations
            l_oBEDomainContext.GetNumerizationReportByOperator(
                StartDate,
                EndDate,
                delegate(InvokeOperation<IEnumerable<NumerizationOperator>> retr)
                {
                    if (retr.Value != null)
                    {
                        BusyIndicator.RemoveBusyTask();

                        Operators = new ObservableCollection<NumerizationOperator>(retr.Value);

                        //Operators By Date Informations
                        OperatorsByDate = new ObservableCollection<NumerizationOperatorByDate>();

                        foreach (NumerizationOperator item in Operators)
                        {
                            LoadChartOperatorsByDateInformations(l_oBEDomainContext, item);
                        }
                    }
                },
                null);
        }

        #endregion Methods
    }
}